﻿using System;
using System.ComponentModel;

using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Wpf.Events;

using WpfTwitterClient.Infrastructure.Events;
using WpfTwitterClient.Infrastructure.Services;
using WpfTwitterClient.Modules.Authorization.Views.StatusView;

namespace WpfTwitterClient.Modules.Authorization.Views.AccountView
{
    public class AccountPresenter : IAccountPresenter
    {
        private readonly ITwitterClient twitterClient;
        private readonly IEventAggregator eventAggregator;

        public AccountPresenter(IAccountView view, ITwitterClient service, IEventAggregator eventAggregator)
        {
            this.twitterClient = service;
            this.eventAggregator = eventAggregator;
            this.View = view;
            this.View.Model = new AccountPresentationModel();

            this.View.GetTwitterPin += this.View_GetTwitterPin;
            this.View.AuthorizeApp += this.View_AuthorizeApp;

            eventAggregator.GetEvent<ConnectedEvent>().Subscribe(this.ConnectedEventHandler, ThreadOption.UIThread, true);
            eventAggregator.GetEvent<NotAuthorizedEvent>().Subscribe(this.NotAuthorizedEventHandler, ThreadOption.UIThread, true);
        }

        public void NotAuthorizedEventHandler(string str)
        {
            this.View.Model.HeaderInfo = "Accounts";
        }

        public void ConnectedEventHandler(string arg)
        {
            var user = this.twitterClient.GetUser();

            if (user != null)
            {
                this.View.Model.HeaderInfo = user.ScreenName;
            }
        }

        private void SetStatusMessage(string message)
        {
            this.eventAggregator.GetEvent<StatusEvent>().Publish(message);
        }

        private void View_AuthorizeApp(object sender, DataEventArgs<string> e)
        {
            this.SetStatusMessage("Making authorization request to twitter.com");

            var worker = new BackgroundWorker();
            
            worker.RunWorkerCompleted += this.GetAccessTokenCompleted;
            worker.DoWork += this.GetAccessToken;
            worker.RunWorkerAsync(e.Value);
        }

        private void GetAccessToken(object sender, DoWorkEventArgs e)
        {
            e.Result = this.twitterClient.GetAccessToken(e.Argument as string);            
        }

        private void GetAccessTokenCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var authorized = (bool)e.Result;
            
            if (!authorized)
            {
                this.SetStatusMessage("Failed to authorize with Twitter. Please try again.");
                return;
            }

            this.SetStatusMessage("Verfiying credentials..");
            var user = this.twitterClient.GetUser();
            if (user != null)
            {
                this.eventAggregator.GetEvent<ConnectedEvent>().Publish(null);
            }

            this.SetStatusMessage(user != null
                           ? string.Format(string.Format("{0} logged in", user.ScreenName))
                           : "Error: could not verify credentials");
        }

        private void View_GetTwitterPin(object sender, EventArgs e)
        {
                this.SetStatusMessage("Connecting to twitter to get token..");
                var authWorker = new BackgroundWorker();
                authWorker.DoWork += new DoWorkEventHandler(this.authWorker_DoWork);
                authWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.authWorker_RunWorkerCompleted);
                authWorker.RunWorkerAsync();
        }

        void authWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                SetStatusMessage("Opening browser window..");
                System.Diagnostics.Process.Start(e.Result as string);
                SetStatusMessage("Please enter Pin");
            }
            else
            {
                SetStatusMessage("Error: Could not connect to the twitter website");
            }
        }

        void authWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = twitterClient.GetRequestToken();
        }

        public IAccountView View { get; set; }
    }
}
